home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 20 code / Scripting the Finder / Finder Tricks / MenuHandler.cp < prev    next >
Encoding:
Text File  |  1994-10-04  |  9.7 KB  |  380 lines  |  [TEXT/MMCC]

  1. /*================================================================================
  2.     MenuHandler.c
  3.     
  4.     ©1991-4 Greg Anderson
  5.     greggor@apple.com
  6.     
  7.     Menu bar routines
  8. ================================================================================*/
  9. #include <Balloons.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <AppleEvents.h>
  13.  
  14. #include "MenuHandler.h"
  15. #include "WindowHandler.h"
  16.  
  17. #include "StringUtilities.h"
  18. #include "MenuTable.h"
  19. #include "AboutBox.h"
  20.  
  21. /*
  22. // Prototypes for private functions:
  23. */
  24. void                    FixupMenu( MenuHandle menuHand, short menu, short item );
  25. short                    NextLargestMenuID( short menuID );
  26. short                    FindItemID( short itemID );
  27. short                    FindMenuInTable( short menu, short item );
  28. void                    ProcessRange( short itemID, short groupSize, menuProc theProc, short param );
  29. void                    SetEnable( MenuHandle menuHand, short item, short enableFlag );
  30. void                    SetEnableRange( short itemID, short groupSize, short enableFlag );
  31. void                    DisableRange( short itemID, short groupSize );
  32. void                    EnableRange( short itemID, short groupSize );
  33. void                    CallCheckItem( MenuHandle menuHand, short item, short flag );
  34. void                    UncheckRange( short itemID, short groupSize );
  35. void                    DoDA( short theItem );
  36.  
  37. /*----------------------------------------------------------------------
  38. // SetupMenuBar
  39. //
  40. // Set up and display the menu bar
  41. ----------------------------------------------------------------------*/
  42. void SetupMenuBar(short startMenu, short endMenu)
  43. {
  44.     MenuHandle        menuHand;
  45.     MenuHandle        helpMenu;
  46.     Handle            menuResource;
  47.     char            menuTitle[256];
  48.     short            smallestMenuID = 0x7FFF;
  49.     short            numberOfMenus;
  50.     short            menuResourceID;
  51.     ResType            menuResourceType;
  52.     Str255            menuResourceName;
  53.     short            menuID;
  54.     short            item;
  55.     short            option;
  56.     OSErr            err;
  57.     
  58.     /*
  59.     // Load all of the menus.
  60.     */
  61.     for( menuResourceID=startMenu; menuResourceID <= endMenu; ++menuResourceID )
  62.     {
  63.         menuHand = GetMenu( menuResourceID );
  64.         if( menuHand )
  65.         {
  66.             /*
  67.             // Pull out the MENU ID of this menu.  The menu ID
  68.             // of a menu is DIFFERENT THAN its resource ID.
  69.             // The menu ID is the value that will be passed back
  70.             // to your application in the high word of the result
  71.             // of the function MenuSelect.
  72.             //
  73.             // Using ResEdit 2.1, you can set the Menu ID of
  74.             // a menu by selecting the "Edit Menu & MDEF ID"
  75.             // command in the "MENU" menu.
  76.             */
  77.             menuID = (*menuHand)->menuID;
  78.             /*
  79.             // Remember the ID of the menu with the smallest
  80.             // ID.  This menu is assumed to be the Apple Menu.
  81.             */
  82.             if( menuID < smallestMenuID )
  83.                 smallestMenuID = menuID;
  84.             /*
  85.             // Insert the menu in the menu bar
  86.             */
  87.             InsertMenu( menuHand, 0 );
  88.         }
  89.     }
  90.     /*
  91.     // Insert desk accessories into the Apple menu.
  92.     */
  93.     AddResMenu( GetMHandle(smallestMenuID),'DRVR');
  94.     /*
  95.     // Draw the menu bar
  96.     */
  97.     DrawMenuBar();
  98. }
  99.  
  100. /*----------------------------------------------------------------------
  101. // FindItemID
  102. //
  103. // Find 'itemID' within the menuTable & return the index it was
  104. // found at
  105. ----------------------------------------------------------------------*/
  106. short FindItemID( short itemID )
  107. {
  108.     short        i;
  109.     
  110.     for(i=0;menuTable[i].itemID;++i)
  111.     {
  112.         if( menuTable[i].itemID == itemID )
  113.             return( i );
  114.     }
  115.     return( -1 );
  116. }
  117.  
  118. /*----------------------------------------------------------------------
  119. // AddItemIDtoTable
  120. //
  121. // Add an itemID to the menutable
  122. ----------------------------------------------------------------------*/
  123. void AddItemIDtoTable( short itemID, short menu, short item )
  124. {
  125.     short        i;
  126.     
  127.     i = FindItemID( itemID );
  128.     if( i != -1 )
  129.     {
  130.         menuTable[i].menu = menu;
  131.         menuTable[i].item = item;
  132.     }
  133. }
  134.  
  135. /*----------------------------------------------------------------------
  136. // FindMenuInTable
  137. //
  138. // Find 'itemID' within the menuTable & return the index it was
  139. // found at
  140. ----------------------------------------------------------------------*/
  141. short FindMenuInTable( short menu, short item )
  142. {
  143.     short        i;
  144.     
  145.     for(i=0;menuTable[i].itemID;++i)
  146.     {
  147.         if( (menuTable[i].menu == menu) && (menuTable[i].item == item) )
  148.             return( i );
  149.     }
  150.     return( -1 );
  151. }
  152.  
  153. /*----------------------------------------------------------------------
  154. // ProcessRange
  155. //
  156. // Process a range of menu item ids
  157. ----------------------------------------------------------------------*/
  158. void ProcessRange( short itemID, short groupSize, menuProc theProc, short param )
  159. {
  160.     MenuHandle    menuHand;
  161.     short        firstID;
  162.     short        i;
  163.     short        j;
  164.     
  165.     firstID = itemID - (itemID % groupSize);
  166.     for(j=firstID;j<firstID+groupSize;++j)
  167.     {
  168.         i = FindItemID(j);
  169.         if( i > -1 )
  170.         {
  171.             menuHand = GetMHandle(menuTable[i].menu);
  172.             if( menuHand != nil )
  173.                 (*theProc)(menuHand,menuTable[i].item,param);
  174.         }
  175.     }
  176. }
  177.  
  178. /*----------------------------------------------------------------------
  179. // SetEnable
  180. //
  181. // Used by SetEnableRange
  182. ----------------------------------------------------------------------*/
  183. void SetEnable( MenuHandle menuHand, short item, short enableFlag )
  184. {
  185.     if( enableFlag )
  186.         EnableItem(menuHand,item);
  187.     else
  188.         DisableItem(menuHand,item);
  189. }
  190.  
  191. /*----------------------------------------------------------------------
  192. // SetEnableRange
  193. //
  194. // Either enable or disable a range of menu items
  195. ----------------------------------------------------------------------*/
  196. void SetEnableRange( short itemID, short groupSize, short enableFlag )
  197. {
  198.     ProcessRange( itemID, groupSize, SetEnable, enableFlag );
  199. }
  200.  
  201. /*----------------------------------------------------------------------
  202. // DisableRange
  203. //
  204. // Disable a range of menu items
  205. ----------------------------------------------------------------------*/
  206. void DisableRange( short itemID, short groupSize )
  207. {
  208.     SetEnableRange( itemID, groupSize, false );
  209. }
  210.  
  211. /*----------------------------------------------------------------------
  212. // EnableRange
  213. //
  214. // Enable a range of menu items
  215. ----------------------------------------------------------------------*/
  216. void EnableRange( short itemID, short groupSize )
  217. {
  218.     SetEnableRange( itemID, groupSize, true );
  219. }
  220.  
  221. /*----------------------------------------------------------------------
  222. // CallCheckItem
  223. //
  224. // This routine is necessary because 'CheckItem' is an inline
  225. // function,and cannot be passed as a procedure pointer
  226. ----------------------------------------------------------------------*/
  227. void CallCheckItem( MenuHandle menuHand, short item, short flag )
  228. {
  229.     CheckItem(menuHand,item,flag);
  230. }
  231.  
  232. /*----------------------------------------------------------------------
  233. // UncheckRange
  234. //
  235. // Remove the check mark from any (& every) menu item in a given menu
  236. ----------------------------------------------------------------------*/
  237. void UncheckRange( short itemID, short groupSize )
  238. {
  239.     ProcessRange( itemID, groupSize, CallCheckItem, false );
  240. }
  241.  
  242. /*----------------------------------------------------------------------
  243. // CheckOneItem
  244. //
  245. // Place a check mark by one item in a menu; remove the checks from
  246. // all other items in the group
  247. ----------------------------------------------------------------------*/
  248. void CheckOneItem( short itemID, short groupSize )
  249. {
  250.     UncheckRange( itemID, groupSize );
  251.     ProcessRange( itemID, 1, CallCheckItem, true );
  252. }
  253.  
  254. /*----------------------------------------------------------------------
  255. // SetupMenuItems
  256. //
  257. // Enable all menus that need enabling; disable all that need
  258. // disabling; put check marks by the menus that need check marks.
  259. ----------------------------------------------------------------------*/
  260. void SetupMenuItems()
  261. {
  262.     OSErr err = noErr;
  263.     
  264.     /*
  265.     // Enable the "Close Window" menu item if there is an open window
  266.     */
  267.     SetEnableRange(M_CLOSEFRONT, 1, (FrontWindow() != nil));
  268.     
  269.     /*
  270.     // First, enable / disable all menus based
  271.     // on which of the menu's enable requirement
  272.     // flags match the menu enable flags in the
  273.     // frontmost window.
  274.     */
  275.     Try
  276.     {
  277.         FrontWindowHandler()->SetupMenus();
  278.     }
  279.     Catch(err)
  280.     {
  281.     }
  282. }
  283.  
  284. /*----------------------------------------------------------------------
  285. // ProcessMenuSelection
  286. //
  287. // Some Menu item selected; find out which one
  288. ----------------------------------------------------------------------*/
  289. void ProcessMenuSelection( long menuResult )
  290. {
  291.     GrafPtr        savePort;
  292.     Str255        selectionName;
  293.     char        selStr[256];
  294.     short        theItem        = menuResult & 0x0FFFF;
  295.     short        theMenu        = menuResult / 0x10000;
  296.     short        i;
  297.     
  298.     if( menuResult )
  299.     {
  300.         GetPort( &savePort );
  301.  
  302.         /*
  303.         // Find the index within the menu table of the item selected.
  304.         */
  305.         i = FindMenuInTable( theMenu, theItem );
  306.  
  307.         OSErr err = noErr;
  308.         Boolean frontWindowDidIt = false;
  309.         
  310.         Try
  311.         {
  312.             /*
  313.             // Give the front window a chance to process the menu command
  314.             */
  315.             frontWindowDidIt = FrontWindowHandler()->ProcessMenuSelection(menuTable[i].itemID);
  316.         }
  317.         Catch(err)
  318.         {
  319.         }
  320.         
  321.         if(frontWindowDidIt == false)
  322.         {
  323.             /*
  324.             // The apple menu is a special case...
  325.             */
  326.             if( theMenu == appleMenu )
  327.             {
  328.                 if(theItem == 1)
  329.                     ShowAboutBox();
  330.                 else
  331.                     DoDA(theItem);
  332.             }
  333.             else
  334.             {
  335.                 /*
  336.                 // If the front window didn't handle the command, and
  337.                 // if there is an entry in the menu function table,
  338.                 // then call it
  339.                 */
  340.                 if(menuTable[i].fMenuFunction != nil)
  341.                 {
  342.                     (*(menuTable[i].fMenuFunction))((CWindowPtr)FrontWindow(),menuTable[i].itemID);
  343.                 }
  344.             }
  345.         }
  346.         /*
  347.         // The OS hilites menus for us, but we must explicitly
  348.         // un-hilite the menu title after we have processed the
  349.         // command
  350.         */
  351.         HiliteMenu(0);
  352.         SetPort( savePort );
  353.     }
  354. }
  355.  
  356. /*----------------------------------------------------------------------
  357. // DoDA
  358. //
  359. // A Desk Accessory has been opened
  360. ----------------------------------------------------------------------*/
  361. void DoDA( short theItem )
  362. {
  363.     Str255        DAname;
  364.     
  365.     GetItem( GetMHandle(appleMenu), theItem, DAname );
  366.     OpenDeskAcc(DAname);
  367. }
  368.  
  369. /*----------------------------------------------------------------------
  370. // CloseFrontWindow
  371. //
  372. // Close the frontmost window
  373. ----------------------------------------------------------------------*/
  374. OSErr CloseFrontWindow(CWindowPtr window, short item)
  375. {
  376.     GetWindowHandler(FrontWindow())->CloseWindowByUser();
  377.     
  378.     return noErr;
  379. }
  380.